
package com.x52im.rbchat.logic.chat_friend.utils;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

import com.eva.android.widget.WidgetUtils;
import com.google.gson.Gson;
import com.x52im.rainbowchat.im.dto.QuoteMeta;
import com.x52im.rbchat.MyApplication;
import com.x52im.rbchat.R;
import com.x52im.rainbowchat.im.dto.CMDBody4AddFriendRequest;
import com.x52im.rainbowchat.im.dto.MsgBody4Friend;
import com.x52im.rainbowchat.im.dto.CMDBody4ProcessFriendRequest;
import com.x52im.rainbowchat.common.dto.cnst.UserProtocalsType;
import com.x52im.rainbowchat.http.logic.dto.RosterElementEntity;
import com.x52im.rainbowchat.im.dto.RevokedMeta;
import com.x52im.rbchat.cache.AlarmsProvider;
import com.x52im.rbchat.logic.chat_root.model.ContactMeta;
import com.x52im.rbchat.logic.chat_root.model.FileMeta;
import com.x52im.rbchat.logic.chat_root.model.LocationMeta;
import com.x52im.rbchat.logic.chat_root.model.Message;
import com.x52im.rbchat.logic.chat_root.model.MessageExt;
import com.x52im.rbchat.logic.chat_root.model.VoipRecordMeta;
import com.x52im.rbchat.network.im.SendDataHelper;

import net.x52im.mobileimsdk.server.protocal.Protocal;

import java.util.Observable;
import java.util.Observer;

/**
 * 一对一好友聊天相关消息/指令的发送和解析方法。
 */
public class MessageHelper
{
	private final static String TAG = MessageHelper.class.getSimpleName();
	
	//*********************************************************************** （1）解析接收的消息或指令 START
	/**
	 * 解析由服务发过来的加好友被拒的实时信息（由服务端通知加好友发起人A）.
	 * 
	 * <p>
	 * 此场景一般是：A加B的好友请求被B拒绝了，服务器实时把此情况反馈给客户A，以便A
	 * 能即时知会哦。
	 * 
	 * @param originalMsg
	 * @return 返回的是B的个人信息（此信息仅包含B存放在数据库中的数据，无其它在线状况信息描述）
	 */
	public static RosterElementEntity parseProcessAdd$Friend$Req_SERVER$TO$A_REJECT_RESULTMessage(String originalMsg)
	{
		System.out.println("!!!!!!收到服务端发过来的好加友被拒信息："+originalMsg);
		return new Gson().fromJson(originalMsg, RosterElementEntity.class);
	}
	
	/**
	 * 解析由服务发过来的好友个人信息.
	 * 
	 * <p>
	 * 此场景一般是：新好友已成功被添加完成，服务端将建立了好友关系的对方个人信息及时
	 * 发送给本地用户（当然，前提是本地用户是在线的，否则没有必要传过来，以便能及时聊天）。
	 * 
	 * @param originalMsg
	 * @return
	 */
	public static RosterElementEntity parseProcessAdd$Friend$Req_friend$Info$Server$To$ClientMessage(String originalMsg)
	{
		System.out.println("!!!!!!收到服务端发过来的新好友信息："+originalMsg);
		return new Gson().fromJson(originalMsg, RosterElementEntity.class);
	}
	
	/**
	 * 解析由服务端通知在线被加好友者：收到了加好友请求.
	 * 
	 * @param originalMsg
	 * @return
	 */
	public static RosterElementEntity parseAddFriendRequestInfo_server$to$b(String originalMsg)
	{
		System.out.println("!!!!!!收到服务端转发的加好友请求："+originalMsg);
		return new Gson().fromJson(originalMsg, RosterElementEntity.class);
	}
	
	/**
	 * 解析由服务端反馈给加好友发起人的错误信息(出错的可能是：该好友
	 * 已经存在于我的好友列表中、插入好友请求到db中时出错等)
	 * 
	 * @param originalMsg
	 * @return 错误信息（文本）
	 */
	public static String parseAddFriendRequestResponse_for$error_server$to$a(String originalMsg)
	{
		return originalMsg;
	}
	
	public static String pareseRecieveOnlineNotivication(String msg)
	{
	    // 通知内容就是这个上线用户的Uid
	    String uid = msg;
		System.out.println("!!!!!!!!!!!!》》收到用户"+uid+"的上线通知！");
		return uid;
	}
	
	public static String pareseRecieveOfflineNotivication(String msg)
	{
        // 通知内容就是这个下线用户的Uid
        String uid = msg;
		System.out.println("!!!!!!!!!!!!《《收到用户"+uid+"的下线通知！");
		return uid;
	}
    //*********************************************************************** （1）解析接收的消息或指令 END


    //*********************************************************************** （2）发出的消息或指令(异步) START
    /**
     * 将指定的图片消息发送给聊天中的好友（异步方式）.
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
     *
     * @param message 文本消息，如果该文本为null或空字符串则不会真正执行发送过程
	 * @param quoteMeta 消息引用信息，此字段可为空（表示本条无引用消息）
	 * @param sucessObsExtra 消息发送完成后，额外要做的事
     * @return code:0 表示发送成功，否则错误码
     * @see #sendMessageAsync(Activity, int, String, String, String, Observer)
     */
    public static void sendPlainTextMessageAsync(final Activity activity
            , final String friendUID, final String message
			, final QuoteMeta quoteMeta
			, final Observer sucessObsExtra)
    {
        // 先生成指纹码
        final String fingerPring = Protocal.genFingerPrint();

		// 消息指令通过网络发送成功后要通知的观察者
		Observer sendSucessObs = (o, arg) -> {
			// 消息数据对象（用于ui界面显示）
			Message m = MessageExt.createChatMsgEntity_OUTGO_TEXT(message, fingerPring);
			// 尝试设置消息引用信息（当前仅针对文本消息有意义），以便用于ui显示
			m.setQuoteMeta(quoteMeta);

			// 消息发送成功后，将此消息数据放到聊天列表的数据模型中（让UI进行显示）
			ChatDataHelper.addChatMessageData_outgoing(activity, friendUID, m);

			// 消息发送调用者的额外要做的事
			if(sucessObsExtra != null)
				sucessObsExtra.update(null, m);
		};

		// 调用真正的消息指令发送方法
        sendMessageAsync(activity, MsgBody4Friend.TYPE_TEXT, friendUID, message, fingerPring, quoteMeta, sendSucessObs);
    }

    /**
     * 将指定的图片消息发送给聊天中的好友（异步方式）.
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
     *
	 * @param sucessObsExtra 消息发送完成后，额外要做的事
     * @return code:0 表示发送成功，否则错误码
     * @see #sendMessageAsync(Activity, int, String, String, String, Observer)
     */
    public static void sendImageMessageAsync(final Activity activity
            , final String friendUID, final String imageFileName, final String fingerPring, final Observer sucessObsExtra)
    {
		// 消息指令通过网络发送成功后要通知的观察者
		Observer sendSucessObs = (o, arg) -> {
			// 发送图片消息成功后什么也不用做（其它在本异步线程执行前图片消息就已经放入到聊天列表了，这是与普通消息最大的区别哦）
			// do nothing

			// 消息发送调用者的额外要做的事
			if(sucessObsExtra != null)
				sucessObsExtra.update(null, null);
		};

		// 调用真正的消息指令发送方法
        sendMessageAsync(activity, MsgBody4Friend.TYPE_IMAGE, friendUID, imageFileName, fingerPring, sendSucessObs);
    }

    /**
     * 将指定的语音留言消息发送给聊天中的好友（异步方式）.
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
     *
	 * @param sucessObsExtra 消息发送完成后，额外要做的事
     * @return code:0 表示发送成功，否则错误码
     */
    public static void sendVoiceMessageAsync(final Activity activity
            , final String friendUID, final String voiceFileName, final String fingerPring, final Observer sucessObsExtra)
    {
		// 消息指令通过网络发送成功后要通知的观察者
		Observer sendSucessObs = (o, arg) -> {
			// 发送语音消息成功后什么也不用做（其它在本异步线程执行前语音消息就已经放入到聊天列表了，这是与普通消息最大的区别哦）
			// do nothing

			// 消息发送调用者的额外要做的事
			if(sucessObsExtra != null)
				sucessObsExtra.update(null, null);
		};

		// 调用真正的消息指令发送方法
        sendMessageAsync(activity, MsgBody4Friend.TYPE_VOICE, friendUID, voiceFileName, fingerPring, sendSucessObs);
    }

    /**
     * 将指的礼品（真正的礼品发送，是要涉及积分处理的）消息发送给聊天中的好友（异步方式）.
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
     *
     * @param giftIdent 参见  {@link MsgBody4Friend}中的赠送礼品消息类型
	 * @param sucessObsExtra 消息发送完成后，额外要做的事
     * @return code:0 表示发送成功，否则错误码
     * @see #sendMessageAsync(Activity, int, String, String, String, Observer)
     */
    public static void sendGift$For$SendMessageAsync(final Activity activity
            , final String friendUID, final String giftIdent, final Observer sucessObsExtra)
    {
        // 先生成指纹码
        final String fingerPring = Protocal.genFingerPrint();

		// 消息指令通过网络发送成功后要通知的观察者
		Observer sendSucessObs = (o, arg) -> {
			// 消息发送成功后，将此消息数据放到聊天列表的数据模型中（让UI进行显示）
			Message m = ChatDataHelper.addChatMessageData_outgoing(activity, friendUID, MessageExt.createChatMsgEntity_OUTGO_GIFT$FOR$SEND(giftIdent, fingerPring));

			// 消息发送调用者的额外要做的事
			if(sucessObsExtra != null)
				sucessObsExtra.update(null, m);
		};

		// 调用真正的消息指令发送方法
        sendMessageAsync(activity, MsgBody4Friend.TYPE_GIFT$SEND, friendUID, giftIdent, fingerPring, sendSucessObs);
    }
    /**
     * 将指定的索取礼品（仅是索取，跟普通文本消息逻辑上是一样的，不涉及积分处理）消息发送给聊天中的好友（异步方式）.
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
     *
     * @param giftIdent 参见  {@link MsgBody4Friend}中的索取礼品消息类型
	 * @param sucessObsExtra 消息发送完成后，额外要做的事
     * @return code:0 表示发送成功，否则错误码
     * @see #sendMessageAsync(Activity, int, String, String, String, Observer)
     */
    public static void sendGift$For$GetMessageAsync(final Activity activity
            , final String friendUID, final String giftIdent, final Observer sucessObsExtra)
    {
        // 先生成指纹码
        final String fingerPring = Protocal.genFingerPrint();

		// 消息指令通过网络发送成功后要通知的观察者
		Observer sendSucessObs = (o, arg) -> {
			// 消息发送成功后，将此消息数据放到聊天列表的数据模型中（让UI进行显示）
			Message m = ChatDataHelper.addChatMessageData_outgoing(activity, friendUID, MessageExt.createChatMsgEntity_OUTGO_GIFT$FOR$GET(giftIdent, fingerPring));

			// 消息发送调用者的额外要做的事
			if(sucessObsExtra != null)
				sucessObsExtra.update(null, m);
		};

		// 调用真正的消息指令发送方法
        sendMessageAsync(activity, MsgBody4Friend.TYPE_GIFT$GET, friendUID, giftIdent, fingerPring, sendSucessObs);
    }

    /**
     * 将指定的文件消息发送给聊天中的好友（异步方式）.
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
     *
     * @param content 文件消息的内容就是FileMeta对象
	 * @param sucessObsExtra 消息发送完成后，额外要做的事
     * @return code:0 表示发送成功，否则错误码
     * @see #sendMessageAsync(Activity, int, String, String, String, Observer)
     * @since 4.3
     */
    public static void sendFileMessageAsync(final Activity activity
            , final String friendUID, final FileMeta content, final String fingerPring
            , final Observer sucessObsExtra)
    {
		// 消息指令通过网络发送成功后要通知的观察者
		Observer sendSucessObs = (o, arg) -> {
			// 发送文件消息成功后什么也不用做（其它在本异步线程执行前语音消息就已经放入到聊天列表了，这是与普通消息最大的区别哦）
			// do nothing

			// 消息发送调用者的额外要做的事
			if(sucessObsExtra != null)
				sucessObsExtra.update(null, null);
		};

		// 调用真正的消息指令发送方法
        sendMessageAsync(activity, MsgBody4Friend.TYPE_FILE, friendUID, new Gson().toJson(content), fingerPring, sendSucessObs);
    }

    /**
     * 将指定的短视频消息发送给聊天中的好友（异步方式）.
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
     *
     * @param content 短视频消息的内容就是FileMeta对象
	 * @param sucessObsExtra 消息发送完成后，额外要做的事
     * @return code:0 表示发送成功，否则错误码
     * @see #sendMessageAsync(Activity, int, String, String, String, Observer)
     * @since 4.4
     */
    public static void sendShortVideoMessageAsync(final Activity activity
            , final String friendUID, final FileMeta content, final String fingerPring, final Observer sucessObsExtra)
    {
		// 消息指令通过网络发送成功后要通知的观察者
		Observer sendSucessObs = (o, arg) -> {
			// 发送短视频消息成功后什么也不用做（其它在本异步线程执行前语音消息就已经放入到聊天列表了，这是与普通消息最大的区别哦）
			// do nothing

			// 消息发送调用者的额外要做的事
			if(sucessObsExtra != null)
				sucessObsExtra.update(null, null);
		};

		// 调用真正的消息指令发送方法
        sendMessageAsync(activity, MsgBody4Friend.TYPE_SHORTVIDEO, friendUID, new Gson().toJson(content), fingerPring, sendSucessObs);
    }

	/**
	 * 将指定的个人名片消息发送给聊天中的好友（异步方式）.
	 * <p>
	 * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
	 * </p>
	 *
	 * @param content 文件消息的内容就是ContactMeta对象
	 * @param sucessObsExtra 消息发送完成后，额外要做的事
	 * @return code:0 表示发送成功，否则错误码
	 * @see #sendMessageAsync(Activity, int, String, String, String, Observer)
	 * @since 4.3
	 */
	public static void sendContactMessageAsync(final Activity activity
			, final String friendUID, final ContactMeta content, final Observer sucessObsExtra)
	{
		// 先生成指纹码
		final String fingerPring = Protocal.genFingerPrint();

		// 消息指令通过网络发送成功后要通知的观察者
		Observer sendSucessObs = (o, arg) -> {
			// 消息发送成功后，将此消息数据放到聊天列表的数据模型中（让UI进行显示）
			Message m = ChatDataHelper.addChatMessageData_outgoing(activity, friendUID, MessageExt.createChatMsgEntity_OUTGO_CONTACT(content, fingerPring));

			// 消息发送调用者的额外要做的事
			if(sucessObsExtra != null)
				sucessObsExtra.update(null, m);
		};

		// 调用真正的消息指令发送方法
		sendMessageAsync(activity, MsgBody4Friend.TYPE_CONTACT, friendUID, new Gson().toJson(content), fingerPring, sendSucessObs);
	}

	/**
	 * 将指定的位置消息发送给聊天中的好友（异步方式）.
	 * <p>
	 * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
	 * </p>
	 *
	 * @param content 文件消息的内容就是LocationMeta对象
	 * @param sucessObsExtra 消息发送完成后，额外要做的事
	 * @return code:0 表示发送成功，否则错误码
	 * @see #sendMessageAsync(Activity, int, String, String, String, Observer)
	 * @since 6.0
	 */
	public static void sendLocationMessageAsync(final Activity activity
			, final String friendUID, final LocationMeta content, final Observer sucessObsExtra)
	{
		// 先生成指纹码
		final String fingerPring = Protocal.genFingerPrint();

		// 消息指令通过网络发送成功后要通知的观察者
		Observer sendSucessObs = (o, arg) -> {
			// 消息发送成功后，将此消息数据放到聊天列表的数据模型中（让UI进行显示）
			Message m = ChatDataHelper.addChatMessageData_outgoing(activity, friendUID, MessageExt.createChatMsgEntity_OUTGO_LOCATION(content, fingerPring));

			// 消息发送调用者的额外要做的事
			if(sucessObsExtra != null)
				sucessObsExtra.update(null, m);
		};

		// 调用真正的消息指令发送方法
		sendMessageAsync(activity, MsgBody4Friend.TYPE_LOCATION, friendUID, new Gson().toJson(content), fingerPring, sendSucessObs);
	}

	/**
	 * 将实时音视频聊天记录消息发送给聊天中的好友（异步方式）.
	 * <p>
	 * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
	 *
	 * @param content 文件消息的内容就是VoipRecordMeta对象
	 * @param sucessObsExtra 消息发送完成后，额外要做的事
	 * @return code:0 表示发送成功，否则错误码
	 * @see #sendMessageAsync(Context, int, String, String, String, Observer)
	 * @since 10.0
	 */
	public static void sendVoipRecordMessageAsync(final Context context
			, final String friendUID, final VoipRecordMeta content, final Observer sucessObsExtra)
	{
		// 先生成指纹码
		final String fingerPring = Protocal.genFingerPrint();

		// 消息指令通过网络发送成功后要通知的观察者
		Observer sendSucessObs = (o, arg) -> {
			// 消息发送成功后，将此消息数据放到聊天列表的数据模型中（让UI进行显示）
			Message m = ChatDataHelper.addChatMessageData_outgoing(context, friendUID, MessageExt.createChatMsgEntity_OUTGO_VOIPRECORD(content, fingerPring));

			// 消息发送调用者的额外要做的事
			if(sucessObsExtra != null)
				sucessObsExtra.update(null, m);
		};

		// 调用真正的消息指令发送方法
		sendMessageAsync(context, MsgBody4Friend.TYPE_VOIP$RECORD, friendUID, new Gson().toJson(content), fingerPring, sendSucessObs);
	}

	/**
	 * "撤回"消息（异步方式）.
	 *
	 * @param content 消息撤回指令的内容就是RevokedMeta对象
	 * @param sucessObsExtra 消息发送完成后，额外要做的事
	 * @return 返回"撤回"指令自已的指纹码
	 * @see #sendMessageAsync(Activity, int, String, String, String, Observer)
	 */
	public static void sendRevokeMessageAsync(final Activity activity
			, String fingerPrint, final String friendUID, final RevokedMeta content, final Observer sucessObsExtra)
	{
		// 消息指令通过网络发送成功后要通知的观察者
		Observer sendSucessObs = (o, arg) -> {
			// 注意：由于消息"撤回"指令需要等对方的应答回来（也就是对方收到撤回指令后）才能做本地的真正"撤回"逻辑，
			//      所以此观察者中无法立即进行"撤回"处理，余下的本地撤回逻辑将由 MessageRevoingManager来实现！

			// 消息发送调用者的额外要做的事
			if(sucessObsExtra != null)
				sucessObsExtra.update(null, null);
		};

		// 调用真正的消息指令发送方法
		sendMessageAsync(activity, MsgBody4Friend.TYPE_REVOKE, friendUID, new Gson().toJson(content), fingerPrint, sendSucessObs);
	}

	/**
	 * 将指定的文本发送给聊天中的好友（异步方式）.
	 * <p>
	 * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
	 * </p>
	 *
	 * @param messageType 参见  {@link MsgBody4Friend}中的文本消息类型
	 * @param message 文本消息，如果该文本为null或空字符串则不会真正执行发送过程
	 * @param sucessObsExtra 消息发送完成后，额外要做的事
	 * @return code:0 表示发送成功，否则错误码
	 * @see #sendChatMessage(Context, String, MsgBody4Friend, String)
	 */
	private static void sendMessageAsync(final Context context
			, final int messageType
			, final String friendUID
			, final String message
			, final String fingerPring
			, Observer sucessObs)
	{
		MessageHelper.sendMessageAsync(context, messageType, friendUID, message, fingerPring, null, sucessObs);
	}

    /**
     * 将指定的文本发送给聊天中的好友（异步方式）.
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
     *
     * @param messageType 参见  {@link MsgBody4Friend}中的文本消息类型
     * @param message 文本消息，如果该文本为null或空字符串则不会真正执行发送过程
	 * @param quoteMeta 消息引用信息（当前仅用于文本消息时），此字段可为空（表示本条无引用消息）
	 * @param sucessObsExtra 消息发送完成后，额外要做的事
     * @return code:0 表示发送成功，否则错误码
     * @see #sendChatMessage(Context, String, MsgBody4Friend, String)
     */
    private static void sendMessageAsync(final Context context
            , final int messageType
            , final String friendUID
            , final String message
            , final String fingerPring
			, final QuoteMeta quoteMeta
            , Observer sucessObs)
    {
        if (message != null && message.length() > 0)
        {
            final RosterElementEntity currentChattingUser = MyApplication.getInstance2()
                    .getIMClientManager().getFriendsListProvider().getFriendInfoByUid2(friendUID);

            // 出现此种情形的可能发生于：我已把对方删除，但从首先对方原先发过来的Alram点到ChatActivity时就会出现这种情况哦！
            if(currentChattingUser == null) {
                WidgetUtils.showToastLong(context, "ID:"+friendUID+" is not your lover, please check it!", WidgetUtils.ToastType.WARN);
                return;
            }

            // 新聊天框架中的网络数据发送需要放到异步线程里（Android2.3以上版本要求网络交互不允许发生在主线程里）
            new AsyncTask<Object, Integer, Integer>(){
                // 数据成功发出去后要通知的观察者（目前，新聊天框架在有丢包重传机前，“成功发出”只意味着发出去但不意味着一定能被收到）
                private Observer sucessObs = null;

                @Override
                protected Integer doInBackground(Object... params) {
                    if(params != null)
                        sucessObs = (Observer)params[0];

                    MsgBody4Friend msgBody = MsgBody4Friend.constructFriendChatMsgBody(
                            MyApplication.getInstance2().getIMClientManager().getLocalUserInfo().getUser_uid(), friendUID, message, messageType);
					// 尝试设置消息引用信息
					msgBody.setQuoteMeta(quoteMeta);
                    return MessageHelper.sendChatMessage(context, currentChattingUser.getUser_uid(), msgBody, fingerPring);
                }

                @Override
                protected void onPostExecute(Integer code) {
                    // 消息发送成功
                    if(code == 0) {
                        if(sucessObs != null)
                            sucessObs.update(null, null);

                        // 将本地用户主动发出的临时聊天消息也入到首页消息栏里(像微信这样的IM里，
                        // 为了方便下次查看，自已主动发的消息也放到了首页消息栏（而不限于收到的消息），
                        // 自已发的消息放到首页消息栏仅仅是为了方便，别无他用。)
                        AlarmsProvider.addChatMsgAlarmForLocal(context, messageType, currentChattingUser.getUser_uid(), currentChattingUser.getNickNameWithRemark(), message);
                    } else {
                        Log.e(TAG, "网络发送数据失败，错误码：code="+code);
                        WidgetUtils.showToast(context, context.getString(R.string.chat_message_send_error), WidgetUtils.ToastType.ERROR);
                    }
                }
            }.execute(sucessObs);
        }
    }
    //*********************************************************************** （2）发出的消息或指令(异步) START



    //*********************************************************************** （3）发出的消息或指令(同步) START
	/**
	 * 发送聊天消息（包括普通文本、图片消息、语音留言消息等）给指定user_id的用户.
	 * <b>注意：</b>目前普通文本消息为了提升用户体验，提供QoS支持.
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
	 * 
	 * @param context
	 * @param user_id 当user_id=0时表示发送给服务器，否则发送给指定用户
	 * @param message 要发送的文本消息
	 * @return
	 * @throws Exception
	 */
	public static int sendChatMessage(Context context, String user_id, MsgBody4Friend message, String fingerPrint)
	{
		return SendDataHelper.sendMessageImpl(context, user_id, new Gson().toJson(message), true, fingerPrint, UserProtocalsType.MT03_OF_CHATTING_MESSAGE);
	}
	
	/**
	 * 发送添加好友的请求到服务端(假设此时的发起人是A).
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
	 * 
	 * @param context
	 * @param arm
	 * @return
	 * @throws Exception
	 */
	public static int sendAddFriendRequestToServerMessage(Context context, CMDBody4AddFriendRequest arm)
	{
		// 发送消息时，user_id=0即表示发送给服务端
		return SendDataHelper.sendMessageImpl(context, "0",
				// 注意：加好友的请求是由服务端代发的哦，因为发起人此时不知道对方的user_id
				// 此时开启了QoS==true，目的是保证我发起的加好友请求在丢包的情况下可以重传
				(new Gson().toJson(arm)), true, UserProtocalsType.MT05_OF_ADD_FRIEND_REQUEST_A$TO$SERVER);
	}
	/**
	 * 发送添加好友的请求到服务端(假设此时的发起人是A).
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
     *
	 * @param context
	 * @param friendUid
	 * @param saySomethingToHim 加好友时的验证消息（本消息实际使用时是可能为null的哦）
	 * @return
	 * @throws Exception
	 * @see {@link #sendAddFriendRequestToServerMessage(Context, CMDBody4AddFriendRequest)}
	 */
	public static int sendAddFriendRequestToServerMessage(Context context, String friendUid, String saySomethingToHim)
	{
		// 加好友请求原数据（将要发送给服务端的）
		CMDBody4AddFriendRequest arm = new CMDBody4AddFriendRequest();
		arm.setLocalUserUid(MyApplication.getInstance(context).getIMClientManager().getLocalUserInfo().getUser_uid());
		arm.setFriendUserUid(friendUid);
		arm.setDesc(saySomethingToHim);
		
		// 发送消息时，user_id=0即表示发送给服务端
		return sendAddFriendRequestToServerMessage(context, arm);
	}
	
	/**
	 * 发送处理添加好友（同意）的请求到服务端(假设此时的发起人是B（即之前A要添加的好友）).
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
	 * 
	 * @param context
	 * @param pfrm
	 * @return
	 * @throws Exception
	 */
	public static int sendProcessAdd$Friend$Req_B$To$Server_AGREEMessage(Context context, CMDBody4ProcessFriendRequest pfrm)
	{
		// 发送消息时，user_id=0即表示发送给服务端
		return SendDataHelper.sendMessageImpl(context, "0",
				(new Gson().toJson(pfrm))
				, true
				, UserProtocalsType.MT08_OF_PROCESS_ADD$FRIEND$REQ_B$TO$SERVER_AGREE);
	}
	
	/**
	 * 发送处理添加好友（拒绝）的请求到服务端(假设此时的发起人是B（即之前A要添加的好友）).
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
	 * 
	 * @param context
	 * @param pfrm
	 * @return
	 * @throws Exception
	 */
	public static int sendProcessAdd$Friend$Req_B$To$Server_REJECTMessage(Context context, CMDBody4ProcessFriendRequest pfrm)
	{
		// 发送消息时，user_id=0即表示发送给服务端
		return SendDataHelper.sendMessageImpl(context, "0",
				(new Gson().toJson(pfrm))
				, true
				, UserProtocalsType.MT09_OF_PROCESS_ADD$FRIEND$REQ_B$TO$SERVER_REJECT);
	}
	
	/**
	 * 视频聊天：结束本次音视频聊天.
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
	 * 
	 * @param context
	 * @param to_user_id 要接收指令的目标好友
	 * @param localUserUid 指令内容
	 * @return 0 表示指令发送成功，否则返回的是错误码
	 * @throws Exception
	 */
	public static int sendVideoAndVoice$EndChatting_from$a(Context context, String to_user_id, String localUserUid)
	{
		return SendDataHelper.sendMessageImpl(context, to_user_id, localUserUid, true, UserProtocalsType.MT14_OF_VIDEO$VOICE_END$CHATTING);// 此消息需要质量保证
	}
	/**
	 * 解析视频聊天：结束本次音视频聊天.
	 * 
	 * @param originalMsg 包含指点协议头和内容本身的原始消息文本
	 * @return 对方的用户uid
	 */
	public static String pareseVideoAndVoice$EndChatting_from$a(String originalMsg)
	{
		return originalMsg;
	}
	
	/**
	 * 视频聊天：切换到纯音频聊天模式.
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
	 * 
	 * @param context
	 * @param to_user_id 要接收指令的目标好友
	 * @return 0 表示指令发送成功，否则返回的是错误码
	 * @throws Exception
	 */
	public static int sendVideoAndVoice$SwitchToVoiceOnly_from$a(Context context, String to_user_id)
	{
		String localUid = MyApplication.getInstance(context).getIMClientManager().getLocalUserInfo().getUser_uid();
		return SendDataHelper.sendMessageImpl(context, to_user_id, localUid, true, UserProtocalsType.MT15_OF_VIDEO$VOICE_SWITCH$TO$VOICE$ONLY);// 此消息需要质量保证
	}
	/**
	 * 解析视频聊天：切换到纯音频聊天模式 .
	 * 
	 * @param originalMsg 包含指点协议头和内容本身的原始消息文本
	 * @return 对方的用户uid
	 */
	public static String pareseVideoAndVoice$SwitchToVoiceOnly_from$a(String originalMsg)
	{
		return originalMsg;
	}
	
	/**
	 * 视频聊天：切换回音视频聊天模式.
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
	 * 
	 * @param context
	 * @param to_user_id 要接收指令的目标好友
	 * @return 0 表示指令发送成功，否则返回的是错误码
	 * @throws Exception
	 */
	public static int sendVideoAndVoice$SwitchToVoiceAndVideo_from$a(Context context, String to_user_id)
	{
		String localUid = MyApplication.getInstance(context).getIMClientManager().getLocalUserInfo().getUser_uid();
		return SendDataHelper.sendMessageImpl(context, to_user_id
				, localUid
				, true
				, UserProtocalsType.MT16_OF_VIDEO$VOICE_SWITCH$TO$VOICE$AND$VIDEO);// 此消息需要质量保证
	}
	/**
	 * 解析视频聊天：切换回音视频聊天模式 .
	 * 
	 * @param originalMsg 包含指点协议头和内容本身的原始消息文本
	 * @return 对方的用户uid
	 */
	public static String pareseVideoAndVoice$SwitchToVoiceAndVideo_from$a(String originalMsg)
	{
		return originalMsg;
	}
	
	/**
	 * 视频聊天呼叫中：请求视频聊天(发起方A).
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
	 * 
	 * @param context
	 * @param to_user_id 要接收指令的目标好友
	 * @return 0 表示指令发送成功，否则返回的是错误码
	 * @throws Exception
	 */
	public static int sendVideoAndVoiceRequest$Requestting_from$a(Context context, String to_user_id, String localUserUid)
	{
		return SendDataHelper.sendMessageImpl(context, to_user_id,
				localUserUid
				, true
				, UserProtocalsType.MT17_OF_VIDEO$VOICE$REQUEST_REQUESTING$FROM$A
				);// 此消息需要质量保证
	}
	/**
	 * 解析视频聊天呼叫中：请求视频聊天(发起方A) .
	 * 
	 * @param originalMsg 包含指点协议头和内容本身的原始消息文本
	 * @return 对方的用户uid
	 */
	public static String pareseVideoAndVoiceRequest$Requestting_from$a(String originalMsg)
	{
		return originalMsg;
	}
	
	/**
	 * 视频聊天呼叫中：取消视频聊天请求(发起发A).
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
	 * 
	 * @param context
	 * @param to_user_id 要接收指令的目标好友
	 * @return 0 表示指令发送成功，否则返回的是错误码
	 * @throws Exception
	 */
	public static int sendVideoAndVoiceRequest$Abort_from$a(Context context, String to_user_id, String localUserUid)
	{
		return SendDataHelper.sendMessageImpl(context, to_user_id,
				localUserUid
				, true
				, UserProtocalsType.MT18_OF_VIDEO$VOICE$REQUEST_ABRORT$FROM$A);// 此消息需要质量保证
	}
	/**
	 * 解析视频聊天呼叫中：取消视频聊天请求(发起发A).
	 * 
	 * @param originalMsg 包含指点协议头和内容本身的原始消息文本
	 * @return 对方的用户uid
	 */
	public static String pareseVideoAndVoiceRequest$Abort_from$a(String originalMsg)
	{
		return originalMsg;
	}
	
	/**
	 * 视频聊天呼叫中：同意视频聊天请求(接收方B).
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
	 * 
	 * @param context
	 * @param to_user_id 要接收指令的目标好友
	 * @return 0 表示指令发送成功，否则返回的是错误码
	 * @throws Exception
	 */
	public static int sendVideoAndVoiceRequest$Accept_to$a(Context context, String to_user_id, String localUserUid)
	{
		return SendDataHelper.sendMessageImpl(context, to_user_id,
				localUserUid
				, true
				, UserProtocalsType.MT19_OF_VIDEO$VOICE$REQUEST_ACCEPT$TO$A
				);// 此消息需要质量保证
	}
	/**
	 * 解析视频聊天呼叫中：同意视频聊天请求(接收方B).
	 * 
	 * @param originalMsg 包含指点协议头和内容本身的原始消息文本
	 * @return 对方的用户uid
	 */
	public static String pareseVideoAndVoiceRequest$Accept_to$a(String originalMsg)
	{
		return originalMsg;
	}
	
	/**
	 * 视频聊天呼叫中：拒绝视频聊天请求(接收方B).
     * <p>
     * 说明：安卓2.3及以后系统中规定：发送网络数据须在单独的线程中。
     * </p>
	 * 
	 * @param context
	 * @param to_user_id 要接收指令的目标好友
	 * @return 0 表示指令发送成功，否则返回的是错误码
	 * @throws Exception
	 */
	public static int sendVideoAndVoiceRequest$Reject_to$a(Context context, String to_user_id, String localUserUid)
	{
		return SendDataHelper.sendMessageImpl(context, to_user_id,
				localUserUid
				, true
				, UserProtocalsType.MT20_OF_VIDEO$VOICE$REQUEST_REJECT$TO$A
				);// 此消息需要质量保证
	}
	/**
	 * 解析视频聊天呼叫中：拒绝视频聊天请求(接收方B).
	 * 
	 * @param originalMsg 包含指点协议头和内容本身的原始消息文本
	 * @return 对方的用户uid
	 */
	public static String pareseVideoAndVoiceRequest$Reject_to$a(String originalMsg)
	{
		return originalMsg;
	}
    //*********************************************************************** （3）发出的消息或指令(同步) START
}
